package com.rocsun.web.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTException;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.rocsun.auth.AuthUser;
import com.rocsun.constant.CommonConstant;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: rocsun-scali
 * @description:
 * @author: yx.guo
 * @create: 2025-11-09 12:35
 **/
@Slf4j
@Component
public class JwtUtil {

    @Value("${token.secretKey}")
    private String secretKey;

    @Value("${token.refreshTime}")
    private Long refreshTime;

    @Value("${token.expiresTime}")
    private Long expiresTime;

    private JWTSigner SIGNER;

    @PostConstruct
    public void init() {
        this.SIGNER = JWTSignerUtil.hs256(secretKey.getBytes());
    }

    // 生成 Token（传入用户ID、用户名等信息）
    public String createToken(String username, String nickName, String role) {
        Map<String, Object> payload = new HashMap<>();
        payload.put("userName", username);
        payload.put("nickName", nickName);
        payload.put("roles", Lists.newArrayList(role));

        return JWT.create()
                .addPayloads(payload)
                .setExpiresAt(new Date(System.currentTimeMillis() + expiresTime * 1000))
                .sign(SIGNER);
    }

    /**
     * 验证是否过期
     * @param token
     * @return 过期 true 否则 false
     */
    public boolean verifyExpires(String token) {
        try {
            boolean verify = JWTUtil.verify(token, SIGNER);
            if (!verify) {
                log.error("令牌签名无效！");
                return false;
            }
            log.info("令牌签名验证成功");
            return true;
        } catch (TokenExpiredException e) {
            log.info("verifyExpires token expired: {}", e.getMessage(), e);
            return false;
        } catch (JWTException e) {
            log.error("verifyExpires JWTException: {}", e.getMessage(), e);
            return false;
        }
    }

    // 验证 Token 有效性
    public boolean verify(String token) {
        try {
            return JWTUtil.parseToken(token).setSigner(SIGNER).verify();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 校验过期
     *
     * @param token
     * @param expiresTime
     * @return 未过期返回true 否则false
     */
    public boolean verifyExpires(String token, long expiresTime) {
        Object exp = JWTUtil.parseToken(token).getPayload("exp");
        if (ObjectUtil.isEmpty(exp)) {
            return false;
        }

        return Long.parseLong(StrUtil.toString(exp)) > System.currentTimeMillis();
    }

    /**
     * 构建Header返回的Authorization
     * @param userName
     * @param nickName
     * @param role
     * @return
     */
    public String generateAuthorization(String userName, String nickName, String role) {
        return CommonConstant.TOKEN_PREFIX + createToken(userName, nickName, role);
    }

    /**
     * 获取真实token
     * @param authorization
     * @return
     */
    public String getRelToken(String authorization) {
        return authorization.substring(CommonConstant.TOKEN_PREFIX.length());
    }

    /**
     * 解析token获取实例
     * @param token
     * @return
     */
    public AuthUser parseToken(String token) {
        JSONObject payloads = JWTUtil.parseToken(token).getPayloads();
        return AuthUser.builder()
                .userName(payloads.getStr("userName"))
                .nickName(payloads.getStr("nickName"))
                .roles(payloads.getBeanList("roles", String.class))
                .build();
    }

}
